﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Linq;
using Framework.UnitOfWork;
using Framework.Infrastructure.Context.NHibernate;
using Framework.UnitOfWork.NHibernate;
using Framework.Specifications;

namespace Framework.Repositories
{
    /// <summary>
    /// Represents the repository which supports the NHibernate implementation.
    /// </summary>
    /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
    public class NHibernateRepository<TAggregateRoot> : Repository<TAggregateRoot>
        where TAggregateRoot : class, IAggregateRoot, new()
    {
        #region Private Fields
        private readonly ISession session = null;
        //private readonly ISpecificationParser<ICriteria> parser = null;
        #endregion

        #region Ctor
        /// <summary>
        /// Initializes a new instance of <c>NHibernateRepository&lt;TAggregateRoot&gt;</c> class.
        /// </summary>
        /// <param name="context">The instance of the repository context.</param>
        public NHibernateRepository(IUnitOfWork unitOfWork)
            : base(unitOfWork)
        {
            if (unitOfWork.DbContext is NHibernateUnitOfWork)
            {
                NHibernateContext nhContext = unitOfWork.DbContext as NHibernateContext;
                this.session = nhContext.Session;
                //this.parser = nhContext.SpecificationParser;
            }
            else
                throw new Exception("Unit of Work is not NHibernate!");
        }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Adds an entity to the repository.
        /// </summary>
        /// <param name="entity">The entity object to be added.</param>
        protected override void DoAdd(TAggregateRoot entity)
        {
            this.UnitOfWork.RegisterNew(entity);
        }
        /// <summary>
        /// Gets the entity instance from repository by a given key.
        /// </summary>
        /// <param name="key">The key of the entity.</param>
        /// <returns>The instance of the entity.</returns>
        protected override TAggregateRoot DoGetByKey(params object[] keyValues)
        {
            return (TAggregateRoot)this.session.Get(typeof(TAggregateRoot), keyValues[0]);
        }

        /// <summary>
        /// Removes the entity from the repository.
        /// </summary>
        /// <param name="entity">The entity to be removed.</param>
        protected override void DoRemove(TAggregateRoot entity)
        {
            this.UnitOfWork.RegisterDeleted(entity);
        }
        /// <summary>
        /// Updates the entity in the repository.
        /// </summary>
        /// <param name="entity">The entity to be updated.</param>
        protected override void DoUpdate(TAggregateRoot entity)
        {
            this.UnitOfWork.RegisterNew(entity);
        }


        /// <summary>
        /// Checkes whether the aggregate root which matches the given specification exists.
        /// </summary>
        /// <param name="specification">The specification with which the aggregate root should match.</param>
        /// <returns>True if the aggregate root exists, otherwise false.</returns>
        protected override bool DoExists(ISpecification<TAggregateRoot> specification)
        {
            return this.DoFind(specification) != null;
        }
        #endregion

        protected override void DoAdd(IQueryable<TAggregateRoot> entities)
        {
           
        }

        protected override IQueryable<TAggregateRoot> DoGetAll(ISpecification<TAggregateRoot> specification, Expression<Func<TAggregateRoot, dynamic>> sortPredicate, Storage.SortOrder sortOrder, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override IQueryable<TAggregateRoot> DoFindAll(ISpecification<TAggregateRoot> specification, Expression<Func<TAggregateRoot, dynamic>> sortPredicate, Storage.SortOrder sortOrder, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override TAggregateRoot DoGet(ISpecification<TAggregateRoot> specification, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override TAggregateRoot DoFind(ISpecification<TAggregateRoot> specification, Expression<Func<TAggregateRoot, dynamic>> path = null)
        {
            throw new NotImplementedException();
        }

        protected override IQueryable<TAggregateRoot> DoPageFind(int pageIndex, int pageSize, Expression<Func<TAggregateRoot, dynamic>> orderByExpression, ISpecification<TAggregateRoot> specification, bool ascending, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override IQueryable<TAggregateRoot> DoPageFind(int pageIndex, int pageSize, Expression<Func<TAggregateRoot, dynamic>> orderByExpression, ISpecification<TAggregateRoot> specification, bool ascending, ref long totalCount, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override IQueryable<TAggregateRoot> DoPageFind(int pageIndex, int pageSize, string[] orderByFileds, ISpecification<TAggregateRoot> specification, bool ascending, ref long totalCount, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override IQueryable<TAggregateRoot> DoPageFind(int pageIndex, int pageSize, string[] orderByFileds, ISpecification<TAggregateRoot> specification, bool ascending, Expression<Func<TAggregateRoot, dynamic>> includePath = null)
        {
            throw new NotImplementedException();
        }

        protected override long DoCount(ISpecification<TAggregateRoot> specification)
        {
            throw new NotImplementedException();
        }

        protected override long DoCount(Expression<Func<TAggregateRoot, bool>> specification)
        {
            throw new NotImplementedException();
        }
    }
}
